package tge

import (
	"net"
	"errors"
	"io"
	"encoding/binary"
	"math"
	// "os"
	"runtime/debug"
)

// 网络数据包读写，一个完整包由 包长 + 数据包
type MsgParser struct {
	packetLenByte		int 	// 数据包长定义的字节数
	maxLen				uint32
	byteOrder 			binary.ByteOrder 	// 大端、小端节序转换，默认为大端
}

func NewMsgParser() *MsgParser {
	p := &MsgParser{2, math.MaxUint16, binary.BigEndian}
	return p
}

func (p *MsgParser) GetPacketLenByte() int {
	return p.packetLenByte
}

func (p *MsgParser) SetPacketLenByte(packetLenByte int) {
	switch packetLenByte {
	case 1:
		p.maxLen = math.MaxUint8
	case 2:
		p.maxLen = math.MaxUint16
	case 4:
		p.maxLen = math.MaxUint32
	}
	if 1 == packetLenByte || 2 == packetLenByte || 4 == packetLenByte {
		p.packetLenByte = packetLenByte
	}
}

// 设置为小端节序
func (p *MsgParser) SetLittleEndian(littleEndian bool) {
	if littleEndian {
		p.byteOrder = binary.LittleEndian
	} else {
		p.byteOrder = binary.BigEndian
	}
}

// 从网络读取数据包
func (p *MsgParser) Read(conn net.Conn) ([]byte, error) {
	if conn == nil {
		return nil, errors.New("MsgParser can't Read from a nil conn!")
	}
	var b [4]byte
	bufMsgLen := b[:p.packetLenByte]
	
	_, err := io.ReadFull(conn, bufMsgLen)
	if err != nil {
		//logger.Println(err)
		return nil, err
	}

	var msgLen uint32

	switch p.packetLenByte {
	case 1:
		msgLen = uint32(bufMsgLen[0])
	case 2:
		msgLen = uint32(p.byteOrder.Uint16(bufMsgLen))
	case 4:
		msgLen = p.byteOrder.Uint32(bufMsgLen)
	}

	if msgLen >= 65536 {
		logger.Println("MsgParser Read too big data size")
		return nil, errors.New("MsgParser Read too big data size")
	} else if msgLen <= 0 {
		logger.Println("MsgParser Read zero data size")
		return nil, errors.New("MsgParser Read zero data size")
	}

	msgData := make([]byte, msgLen)
	_, err = io.ReadFull(conn, msgData)
	if err != nil {
		//logger.Println(err)
		return nil, err
	}

	return msgData, nil
}

// 向网络写入数据包
func (p *MsgParser) Write(conn net.Conn, args ...[]byte) (int, error) {
	// var msgLen uint32

	// for i := 0; i < len(args); i++ {
	// 	msgLen += uint32(len(args[i]))
	// }
	defer func() {
		if err := recover(); err != nil {
			// logger.Println("============ err", err, msgLen, p)
			debug.PrintStack()
			// os.Exit(1)
		}
	} ()


	// if msgLen > p.maxLen {
	// 	return 0, errors.New("msg to long")
	// }

	// msg := make([]byte, msgLen + uint32(p.packetLenByte))
	// switch p.packetLenByte {
	// case 1:
	// 	msg[0] = byte(msgLen)
	// case 2:
	// 	p.byteOrder.PutUint16(msg, uint16(msgLen))
	// case 4:
	// 	p.byteOrder.PutUint32(msg, msgLen)
	// }

	
	// lenght := p.packetLenByte
	// for i := 0; i < len(args); i++ {
	// 	copy(msg[lenght:], args[i])
	// 	lenght += len(args[i])
	// }

	msg, err := p.BuildMsg(args ...)
	if nil != err {
		return 0, err
	}

	if (conn != nil) {
		return conn.Write(msg)
	}
	return 0, errors.New("conn is nil")
}

func (p *MsgParser) BuildMsg(args ...[]byte) ([]byte, error) {
	var msgLen uint32

	for i := 0; i < len(args); i++ {
		msgLen += uint32(len(args[i]))
	}
	if msgLen > p.maxLen {
		return nil, errors.New("msg to long")
	}

	msg := make([]byte, msgLen + uint32(p.packetLenByte))
	switch p.packetLenByte {
	case 1:
		msg[0] = byte(msgLen)
	case 2:
		p.byteOrder.PutUint16(msg, uint16(msgLen))
	case 4:
		p.byteOrder.PutUint32(msg, msgLen)
	}
	
	lenght := p.packetLenByte
	for i := 0; i < len(args); i++ {
		copy(msg[lenght:], args[i])
		lenght += len(args[i])
	}

	return msg, nil
}

func (p *MsgParser) ParseMsg(msg []byte) ([]byte, error) {
	if (len(msg) >= p.packetLenByte) {
		bufMsgLen := msg[:p.packetLenByte]

		var msgLen uint32

		switch p.packetLenByte {
		case 1:
			msgLen = uint32(bufMsgLen[0])
		case 2:
			msgLen = uint32(p.byteOrder.Uint16(bufMsgLen))
		case 4:
			msgLen = p.byteOrder.Uint32(bufMsgLen)
		}

		if (len(msg) >= p.packetLenByte + int(msgLen)) {
			return msg[p.packetLenByte: p.packetLenByte + int(msgLen)], nil
		}
	}
	return nil, errors.New("msg to short")
}